package team.nmsg.ge.system.dao.impl;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import team.nmsg.ge.system.bean.PageObject;
import team.nmsg.ge.system.dao.INMSCommonDao;
import team.nmsg.ge.system.dao.SysRsTransformer;


@Component
public class NMSCommonDaoImpl implements INMSCommonDao {
	
	@PersistenceContext
	private EntityManager em;
	
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	public EntityManager getEntityManager() {
		return em;
	}
	
	public JdbcTemplate getJdbcTemplate(){
		return jdbcTemplate;
	}
	
	public Object getOneCellBySql(String sql , Object...args){
		
		Query sqlQuery = em.createNativeQuery(sql);
		if( args != null ){
			for( int i=0; i<args.length ;i++ ){
				sqlQuery.setParameter(i+1, args[i]);
			}
		}
		SQLQuery unwrap = sqlQuery.unwrap(SQLQuery.class);
		
		Object uniqueResult = unwrap.uniqueResult();
		
		return uniqueResult;
	}
	
	public <T> T getRowBySql(Class<T> entitClazz , String sql , Object...args){
		
		List<T> queryMultiRowBySql = getMultiRowBySql(entitClazz, sql, args);
		if( queryMultiRowBySql!= null && queryMultiRowBySql.size()>0 ){
			return queryMultiRowBySql.get(0);
		}
		return null;
	}
	
	public <T> List<T> getMultiRowBySql(Class<T> entitClazz , String sql , Object...args){
		Query sqlQuery = em.createNativeQuery(sql);
		if( args != null ){
			for( int i=0; i<args.length ;i++ ){
				sqlQuery.setParameter(i+1, args[i]);
			}
		}
		SQLQuery unwrap = sqlQuery.unwrap(SQLQuery.class);
		unwrap.setResultTransformer( new SysRsTransformer(entitClazz) );
//		unwrap.setResultTransformer(new NMSRsTransformer(entitClazz));
		List<T> list = unwrap.list();
		return list;
	}
	
	public List getMultiRowBySql(String sql , Object...args){
		Query sqlQuery = em.createNativeQuery(sql);
		if( args != null ){
			for( int i=0; i<args.length ;i++ ){
				sqlQuery.setParameter(i+1, args[i]);
			}
		}
		SQLQuery unwrap = sqlQuery.unwrap(SQLQuery.class);
		List list = unwrap.list();
		return list;
	}

	@Override
	public int exeuteUpdate(String sql) {
		
		int nmsExecuteUpdate = exeuteUpdate(sql , null);
		
		return nmsExecuteUpdate;
	}

	@Override
	public int exeuteUpdate(String sql, Object... args) {
		Query sqlQuery = em.createNativeQuery(sql);
		if( args != null ){
			for( int i=0; i<args.length ;i++ ){
				sqlQuery.setParameter(i+1, args[i]);
			}
		}
		SQLQuery unwrap = sqlQuery.unwrap(SQLQuery.class);
		int executeUpdate = unwrap.executeUpdate();
		
		return executeUpdate;
	}

	@Override
	public <T> List<T> getMultiRowBySqlPage(Class<T> entitClazz, String sql,
			int startIndex, int pageSize, Object... args) {
		Query sqlQuery = em.createNativeQuery(sql);
		if( args != null ){
			for( int i=0; i<args.length ;i++ ){
				sqlQuery.setParameter(i+1, args[i]);
			}
		}
		SQLQuery unwrap = sqlQuery.unwrap(SQLQuery.class);
		unwrap.setResultTransformer( new SysRsTransformer(entitClazz) );
		if (pageSize != -1 && startIndex != -1) {
				int arg0 = pageSize * (startIndex /pageSize);
				unwrap.setFirstResult(arg0);
				unwrap.setMaxResults(pageSize);
			}
		List<T> list = unwrap.list();
		return list;
	}

	@Override
	public long getMultiRowCountBySql(String sql, Object... args) {
		Query sqlQuery = em.createNativeQuery(sql);
		if( args != null ){
			for( int i=0; i<args.length ;i++ ){
				sqlQuery.setParameter(i+1, args[i]);
			}
		}
		long count = Long.valueOf(sqlQuery.getResultList().get(0).toString());
		return count;
	}

	@Override
	public <T> PageObject<T> getMultiRowBySqlPage(Class<T> entitClazz,
			String sqlContent, String sqlCount, int startIndex, int pageSize,
			Object... args) {
		PageObject<T> page = new PageObject<T>();
		page.setCurrentEntitys(getMultiRowBySqlPage(entitClazz, sqlContent, startIndex, pageSize, args));
		page.setSumCount(getMultiRowCountBySql(sqlCount, args));
		return page;
	}

	
	public List getResultWithMax( String sql , int maxResult , Object... args) {
		
		Query sqlQuery = em.createNativeQuery(sql);
		if( args != null ){
			for( int i=0; i<args.length ;i++ ){
				sqlQuery.setParameter(i+1, args[i]);
			}
		}
		SQLQuery createSQLQuery = sqlQuery.unwrap(SQLQuery.class);
		createSQLQuery.setMaxResults(maxResult);
		List list = createSQLQuery.list();
		
		return list;
	}

	@Override
	public <T> List<T> getEntitiesBySql(Class<T> entitClazz, String sql,
			Object... args) {
		
		return getMultiRowBySql(entitClazz, sql, args);
	}

	@Override
	public <T> T getEntitiyBySql(Class<T> entitClazz, String sql,
			Object... args) {
		// TODO Auto-generated method stub
		return getRowBySql(entitClazz, sql, args);
	}

	@Override
	public <T> T save(Class clazz, T t) {
		
		Session session = em.unwrap(Session.class);
		
		Serializable save = session.save(t);
		Object object = session.get(clazz, save);
		
		return (T) object;
	}

	@Override
	public <T> T getObject(Class<T> clazz, Serializable id) {
		Session session = em.unwrap(Session.class);
		Object object = session.get(clazz, id);
		return (T)object;
	}

	@Override
	public void updateObject(Object object) {
		Session session = em.unwrap(Session.class);
		session.update(object);
		session.flush();
	}

	@Override
	public void deleteObject(Object object) {
		Session session = em.unwrap(Session.class);
		session.delete(object);
		session.flush();
	}

	@Override
	public <T> T saveObject(Class<T> clazz, T t) {
		// TODO Auto-generated method stub
		return save(clazz, t);
	}

	@Override
	public <T> T getEntityBySql(Class<T> clazz, String sql, Object... params) {
		
		List<T> entitiesBySql = getEntitiesBySql(clazz, sql, params);
		if( entitiesBySql != null && entitiesBySql.size()>0 ){
			T t = entitiesBySql.get(0);
			return t;
		}
		return null;
	}
	
	public Session getHSession(){
		Session session = em.unwrap(Session.class);
		return session;
	}
	
}
